<template>
  <div class="container">
    <div class="page-title">
      <div class="sub-left">
        <h3>环境管理（{{ environmentList.length }}个）</h3>
      </div>
      <div class="sub-right">
        <search placeholder="搜索环境" @change="searchEnv"></search>
        <Button type="primary" @click="addEnvironment" class="button-add" v-if="hasPermission($store, '1', 'NAMESPACE_POST')">
          <Icon type="md-add" />
          <span class="button-name">添加环境</span>
        </Button>
      </div>
    </div>
    <div class="zl-page-loading" v-if="loading">
      <Spin fix></Spin>
    </div>
    <Row :gutter="10" class="env-list" v-else>
      <Col :span="6" v-for="environment in environmentList" :key="environment.environmentId">
        <Card class="env-box" @click.native="goEnvironmentDetail(environment)">
          <div class="env-mani" v-if="environment.status === 'Active'">
            <Tooltip content="导出配置">
              <Icon type="md-open" @click.stop="envDownload(environment)"></Icon>
            </Tooltip>
            <Tooltip content="编辑环境" v-if="hasPermission($store, environment.environmentId, 'NAMESPACE_PUT_ENV')">
              <Icon type="ios-create-outline" @click.stop="envEdit(environment)"></Icon>
            </Tooltip>
            <Tooltip content="删除环境" v-if="hasPermission($store, environment.environmentId, 'NAMESPACE_DELETE_ENV')">
              <Icon type="md-trash" @click.stop="envDelete(environment)"></Icon>
            </Tooltip>
          </div>
          <div class="env-name flex">
            <div class="flex-label">
              <i :class="{'inactive': environment.status !== 'Active'}">{{(environment.environmentName ? environment.environmentName : environment.environmentId) | preName}}</i>
            </div>
            <div class="flex-1 f-nowrap">
              <h4 class="f-nowrap">{{(environment.environmentName ? environment.environmentName : environment.environmentId) }}</h4>
              <div class="f-nowrap">{{ environment.createTime }}</div>
            </div>
          </div>
          <div class="description flex">
            <div class="flex-name">描述：</div>
            <div class="flex-1 f-nowrap">{{ environment.description ? environment.description : '暂无描述' }}</div>
          </div>
        </Card>
      </Col>
    </Row>

    <!-- 添加环境弹窗 -->
    <Modal v-model="envAddVisible" :title="isEdit ? '编辑环境' : '添加环境'" :mask-closable="false">
      <div class="modal-env-add">
        <div class="zl-page-loading" v-if="isLoading">
          <Spin fix></Spin>
        </div>
        <Form :model="envForm" ref="envForm" :rules="envRules" :label-width="120" label-position="left" v-else>
          <FormItem label="环境名称" prop="environmentName">
            <Input v-model.trim="envForm.environmentName" placeholder="请输入环境名称"></Input>
          </FormItem>
          <FormItem label="域名" prop="secondaryDomain">
            <Input v-model.trim="envForm.secondaryDomain" placeholder="请输入环境域名"><span slot="append">{{domainPostfix | domainDot}}</span></Input>
          </FormItem>
          <FormItem label="容器CPU(mCpu)" prop="containerCpu">
            <Row :gutter="8" class="env-cpu">
              <Col span="12">
                <Input v-model.trim="envForm.containerCpu.containerDefaultRequestCpu" placeholder="最小容器CPU">
                  <div slot="prepend">最小值</div>
                </Input>
              </Col>
              <Col span="12">
                <Input v-model.trim="envForm.containerCpu.containerDefaultCpu" placeholder="最大容器CPU">
                  <div slot="prepend">最大值</div>
                </Input>
              </Col>
            </Row>
          </FormItem>
          <FormItem label="容器内存(Gi)" prop="containerMemory">
            <Row :gutter="8" class="env-cpu">
              <Col span="12">
                <Input v-model.trim="envForm.containerMemory.containerDefaultRequestMemory" placeholder="最小容器内存">
                  <div slot="prepend">最小值</div>
                </Input>
              </Col>
              <Col span="12">
                <Input v-model.trim="envForm.containerMemory.containerDefaultMemory" placeholder="最大容器内存">
                  <div slot="prepend">最大值</div>
                </Input>
              </Col>
            </Row>
          </FormItem>
          <FormItem label="描述">
            <Input v-model.trim="envForm.description" placeholder="请输入环境描述"></Input>
          </FormItem>
          <FormItem label="导入配置" v-if="!isEdit">
            <Checkbox v-model="envImportFlag"> </Checkbox>
            <div class="environment-import" v-if="envImportFlag">
              <Upload
                :before-upload="configUploadBefore"
                type="drag"
                action="">
                <div class="env-config-import">
                  <Icon type="ios-cloud-upload" size="52"></Icon>
                  <p>将文件拖到此处，或点击上传</p>
                </div>
              </Upload>
          </div>
          </FormItem>
        </Form>
      </div>
      <div slot="footer">
        <Button type="warning" @click="envCancel">取消</Button>
        <Button type="primary" :loading="isAdding" @click="addEnvironmentConf">确定</Button>
      </div>
    </Modal>
  </div>
</template>

<script>
import Fetch from '@/api/request'
import Search from '@/components/search'

export default {
  components: {Search},
  data() {
    const validateEnvironmentName = (rule, value, callback) => {
      var regName = /^(?![(0-9)-])[a-zA-Z0-9\-\u4e00-\u9fa5]*$/
      if (!value) {
        callback(new Error('请输入名称'))
      } else if (!regName.test(value)) {
        callback(new Error('由英文字母、数字、-、中文组成，不能以数字或-开头'))
      } else if (value.length < 4) {
        callback(new Error('最小长度不能少于4位'))
      } else if (value.length > 64) {
        callback(new Error('最大长度不能大于64位'))
      } else {
        callback()
      }
    }
    const validateDescription = (rule, value, callback) => {
      if (value && value.length > 128) {
        callback(new Error('最大长度不能大于128位'))
      } else {
        callback()
      }
    }
    const validateCpu = (rule, value, callback) => {
      let regCpu = /^\+?[1-9][0-9]*$/
      if (!value.containerDefaultRequestCpu) {
        callback(new Error('请输入容器CPU最小值'))
      } else if (!value.containerDefaultCpu) {
        callback(new Error('请输入容器CPU最大值'))
      } else if (!regCpu.test(value.containerDefaultRequestCpu)) {
        callback(new Error('容器CPU最小值不为整数'))
      } else if (!regCpu.test(value.containerDefaultCpu)) {
        callback(new Error('容器CPU最大值不为整数'))
      } else if (value.containerDefaultCpu <= value.containerDefaultRequestCpu) {
        callback(new Error('容器CPU最大值要大于最小值'))
      } else {
        callback()
      }
    }
    const validateMemory = (rule, value, callback) => {
      let regCpu = /^\d+(\.\d+)?$/
      if (!value.containerDefaultRequestMemory) {
        callback(new Error('请输入容器内存最小值'))
      } else if (!value.containerDefaultMemory) {
        callback(new Error('请输入容器内存最大值'))
      } else if (!regCpu.test(value.containerDefaultRequestMemory)) {
        callback(new Error('容器内存最小值不为整数'))
      } else if (!regCpu.test(value.containerDefaultMemory)) {
        callback(new Error('容器内存最大值不为整数'))
      } else if (value.containerDefaultMemory <= value.containerDefaultRequestMemory) {
        callback(new Error('容器内存最大值要大于最小值'))
      } else {
        callback()
      }
    }
    const validateDomainRequest = (rule, value, callback) => {
      // var regDomainRequest = /[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/
      var regDomainRequest = /^[a-z0-9]+[a-z0-9\-.]*$/
      if (!value) {
        callback(new Error('请输入域名'))
      } else if (!regDomainRequest.test(value)) {
        callback(new Error('由小写字母、数字、-、.组成，以小写字母、数字开头和结尾'))
      } else if (value.length > 128) {
        callback(new Error('域名最大长度不能超过128位'))
      } else {
        callback()
      }
    }
    return {
      conditionInput: '',
      styleObject: {
        width: '200px',
        marginRight: '15px',
        verticalAlign: 'center'
      },
      loading: true,
      environmentList: [],
      originalenvironmentList: [],
      domainPostfix: '',
      envAddVisible: false,
      envForm: {
        environmentName: '',
        description: '',
        containerCpu: {
          containerDefaultCpu: '999',
          containerDefaultRequestCpu: '100'
        },
        containerMemory: {
          containerDefaultMemory: '2',
          containerDefaultRequestMemory: '0.5'
        },
        secondaryDomain: ''
      },
      envRules: {
        environmentName: [
          { required: true, trigger: 'blur', validator: validateEnvironmentName }
        ],
        description: [
          { required: false, trigger: 'blur', validator: validateDescription }
        ],
        containerCpu: [
          { required: true, trigger: 'blur', validator: validateCpu }
        ],
        containerMemory: [
          { required: true, trigger: 'blur', validator: validateMemory }
        ],
        secondaryDomain: [
          { required: true, trigger: 'blur', validator: validateDomainRequest }
        ]
      },
      isAdding: false,
      envName: '',
      envImportFlag: false,
      file: null,
      isEdit: false,
      isLoading: false,
      environmentIdEdit: '',
      importing: ''
    }
  },
  mounted() {
    this.init()
  },
  filters: {
    preName(val) {
      if (val) {
        return val.substring(0, 1)
      }
    },
    domainDot(name) {
      if (name && name.length > 0 && name[0] !== '.') {
        return '.' + name
      } else {
        return name
      }
    }
  },
  methods: {
    // 环境删除
    envDelete(env) {
      this.$Modal.confirm({
        title: '系统提示',
        content: '确定删除环境' + (env.environmentName ? env.environmentName : env.environmentId) + '？',
        loading: true,
        onOk: () => {
          Fetch.delete({
            url: '/api/environments/' + env.environmentId,
            done: () => {
              this.$Modal.remove()
            }
          }).then((res) => {
            this.$Message.success({
              content: '删除环境' + (env.environmentName ? env.environmentName : env.environmentId) + '成功！',
              duration: this.DURATION
            })
            setTimeout(() => {
              this.getAuthPermissions()
              this.init()
              this.$bus.$emit('update-env')
            }, 1000)
          })
        }
      })
    },
    // 环境编辑
    envEdit(env) {
      this.envAddVisible = true
      this.isLoading = true
      this.isEdit = true
      this.environmentIdEdit = env.environmentId
      Fetch.get({
        url: '/api/environments/' + env.environmentId + '/environmentandresourcelimit'
      }).then((res) => {
        if (res && res.code === '0') {
          this.envForm.environmentName = res.data.environmentName
          this.envForm.description = res.data.description
          this.envForm.containerCpu.containerDefaultCpu = res.data.containerDefaultCpu
          this.envForm.containerCpu.containerDefaultRequestCpu = res.data.containerDefaultRequestCpu
          this.envForm.containerMemory.containerDefaultMemory = res.data.containerDefaultMemory
          this.envForm.containerMemory.containerDefaultRequestMemory = res.data.containerDefaultRequestMemory
          this.envForm.secondaryDomain = res.data.secondaryDomain
        } else {
          this.$Message.warning({
            content: res.message,
            duration: this.DURATION
          })
        }
        this.isLoading = false
      }).catch((err) => {
        this.isLoading = false
        this.$Message.error(err.message)
      })
    },
    // 下载环境配置文件
    envDownload(env) {
      if (this.importing.includes(env.environmentId)) {
        this.$Message.info({
          content: '正在下载中，请稍等!',
          duration: this.DURATION
        })
        return
      } else {
        this.importing += ',' + env.environmentId
      }
      Fetch.get({
        url: '/api/common/' + env.environmentId + '/export',
        self: 'then',
        done: () => {
          this.importing.replace(',' + env.environmentId, '')
        }
      }).then((res) => {
        if (res && res.data) {
          let blob = new Blob([res.data])
          let a = document.createElement('a')
          let url = window.URL.createObjectURL(blob)
          a.href = url
          a.download = (env.environmentName ? env.environmentName : env.environmentId) + '.yaml'
          a.click()
        } else {
          this.$Message.warning({
            content: '导出配置出错！',
            duration: this.DURATION
          })
        }
        this.importing = this.importing.replace(',' + env.environmentId, '')
      })
    },
    // 配置文件上传前校验，上传文件个数不能多于5个，每个大小不能大于20M
    configUploadBefore(file) {
      const MAX_SIZE = 20 * 1024 * 1024
      if (file.size > MAX_SIZE) {
        this.$Message.warning({
          content: '上传文件大小大于20M！',
          duration: this.DURATION
        })
        return false
      }
      if (this.file) {
        this.$Message.warning({
          content: '配置文件只能上传一个！',
          duration: this.DURATION
        })
        return false
      }
      this.file = file
    },
    // 进入环境详情页面
    goEnvironmentDetail(environment) {
      if (environment.status !== 'Active') {
        return ''
      }
      this.$router.push('/home/environment/' + environment.environmentId + '/info')
    },
    // 环境列表
    init() {
      this.getEnvironmentList()
      this.getDomain()
    },
    getEnvironmentList() {
      Fetch.get({
        url: '/api/environment'
      }).then(res => {
        if (res && res.code === '0') {
          this.environmentList = res.data
          // 用于搜索改动environment后还原environment
          this.originalenvironmentList = res.data
        } else {
          this.$Message.warning(res.message || '服务器内部错误')
        }
        this.loading = false
      }).catch(err => {
        this.$Message.warning(err.message)
        this.loading = false
      })
    },
    // 根据名称搜索
    searchEnv(envName) {
      let temp = []
      this.originalenvironmentList.forEach((env) => {
        let name = env.environmentName ? env.environmentName : env.environmentId
        if (name.indexOf(envName) !== -1) {
          temp.push(env)
        }
      })
      this.environmentList = temp
    },
    // 获取域名
    getDomain() {
      Fetch.get({
        url: '/api/env/getDomain'
      }).then((res) => {
        if (res && res.code === '0') {
          this.domainPostfix = res.data
          localStorage.setItem('domain', res.data)
        } else {
          this.$Message.warning({
            content: res.message || '服务器内部错误',
            duration: this.DURATION
          })
        }
      }).catch((err) => {
        this.$Message.error({
          content: err.message,
          duration: this.DURATION
        })
      })
    },
    // 添加环境
    addEnvironment() {
      let vm = this
      vm.isEdit = false
      vm.envAddVisible = true
      vm.$nextTick(function () {
        vm.$refs['envForm'].resetFields()
        vm.envForm.environmentName = ''
        vm.envForm.description = ''
        vm.envForm.containerMemory.containerDefaultMemory = '2'
        vm.envForm.containerMemory.containerDefaultRequestMemory = '0.5'
        vm.envForm.containerCpu.containerDefaultCpu = '999'
        vm.envForm.containerCpu.containerDefaultRequestCpu = '100'
        vm.envForm.secondaryDomain = ''
      })
    },
    // 获取用户权限
    getAuthPermissions() {
      Fetch.get({
        url: '/api/auth/permissions',
        self: 'then'
      }).then((res) => {
        this.$store.commit('SET_PERMISSIONS', res.data)
      })
    },
    // 确定添加环境
    addEnvironmentConf() {
      if (this.isAdding) {
        return
      }
      this.$refs.envForm.validate(valid => {
        if (valid) {
          this.isAdding = true
          if (this.isEdit) {
            // 编辑环境
            let params = {
              environmentName: this.envForm.environmentName,
              description: this.envForm.description,
              containerDefaultCpu: this.envForm.containerCpu.containerDefaultCpu,
              containerDefaultRequestCpu: this.envForm.containerCpu.containerDefaultRequestCpu,
              containerDefaultMemory: this.envForm.containerMemory.containerDefaultMemory,
              containerDefaultRequestMemory: this.envForm.containerMemory.containerDefaultRequestMemory,
              secondaryDomain: this.envForm.secondaryDomain
            }
            Fetch.put({
              url: '/api/environments/' + this.environmentIdEdit,
              params
            }).then(res => {
              if (res.code === '0') {
                this.envAddVisible = false
                this.$Message.success('编辑环境成功!')
                this.init()
              } else {
                this.$Message.warning(res.message || '服务器内部错误')
              }
              this.isAdding = false
              this.envImportFlag = false
            }).catch(err => {
              this.isAdding = false
              this.envImportFlag = false
              this.$Message.warning(err.message)
            })
          } else if (this.envImportFlag && this.file) {
            // 导入配置的情况下新增环境
            Fetch.post({
              url: '/api/common/importEnvironment?environmentName=' + this.envForm.environmentName + '&description=' + this.envForm.description +
              '&containerDefaultCpu=' + this.envForm.containerCpu.containerDefaultCpu + '&containerDefaultRequestCpu=' +
              this.envForm.containerCpu.containerDefaultRequestCpu + '&containerDefaultMemory=' + this.envForm.containerMemory.containerDefaultMemory +
              '&containerDefaultRequestMemory=' + this.envForm.containerMemory.containerDefaultRequestMemory + '&secondaryDomain=' +
              this.envForm.secondaryDomain,
              params: {'fileData': this.file},
              type: 'form'
            }).then(res => {
              if (res.code === '0') {
                this.envAddVisible = false
                this.$Message.success('添加环境成功!')
                this.getAuthPermissions()
                this.init()
              } else {
                this.$Message.warning(res.message || '服务器内部错误')
              }
              this.isAdding = false
            }).catch(err => {
              this.isAdding = false
              this.$Message.warning(err.message)
            })
          } else {
            let params = {
              environmentName: this.envForm.environmentName,
              description: this.envForm.description,
              containerDefaultCpu: this.envForm.containerCpu.containerDefaultCpu,
              containerDefaultRequestCpu: this.envForm.containerCpu.containerDefaultRequestCpu,
              containerDefaultMemory: this.envForm.containerMemory.containerDefaultMemory,
              containerDefaultRequestMemory: this.envForm.containerMemory.containerDefaultRequestMemory,
              secondaryDomain: this.envForm.secondaryDomain
            }
            Fetch.post({
              url: '/api/addEnvironment',
              params
            }).then(res => {
              if (res.code === '0') {
                this.envAddVisible = false
                this.$Message.success('添加环境成功!')
                this.getAuthPermissions()
                this.init()
                this.$bus.$emit('update-env')
              } else {
                this.$Message.warning(res.message || '服务器内部错误')
              }
              this.isAdding = false
              this.envImportFlag = false
            }).catch(err => {
              this.isAdding = false
              this.envImportFlag = false
              this.$Message.warning(err.message)
            })
          }
        } else {
          this.$Message.warning('请先按要求填写好环境参数!')
        }
      })
    },
    envCancel() {
      this.envAddVisible = false
    }
  },
  watch: {
    envImportFlag(val) {
      if (val) {
        this.file = null
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  background-color: #f5f7f9;
  .page-title {
    height: 40px;
    line-height: 40px;
    .sub-left {
      display: inline-block;
    }
    .sub-right {
      float: right;
      .search-box {
        vertical-align: top;
        margin-top: 7px;
      }
      .button-add {
        vertical-align: top;
        margin-top: 6px;
        padding: 1px 14px;
        .iconfont:hover {
          color: #fff;
        }
        .button-name {
          display: inline-block;
          vertical-align: top;
          line-height: 26px;
        }
      }
      i {
        display: inline-block;
        line-height: 22px;
        vertical-align: top;
        margin-top: 2px;
        font-size: 14px;
      }
    }
  }
  .env-list {
    padding-top: 10px;
  }
  .env-box {
    position: relative;
    border-radius: 4px;
    margin-bottom: 10px;
    cursor: pointer;
    &:hover {
      background-color: #d8dfe7;
      border-color: #d8dfe7;
      .env-mani {
        display: block;
      }
    }
    .env-mani {
      position: absolute;
      right: 3px;
      top: 3px;
      display: none;
      color: #333;
      font-size: 16px;
      i {
        margin-right: 5px;
        background-color: #fff;
        border-radius: 50%;
        padding: 3px;
      }
    }
    .env-name {
      .flex-1 {
        h4 {
          font-size: 14px;
          color: #333;
        }
      }
      i {
        display: inline-block;
        vertical-align: top;
        width: 32px;
        height: 32px;
        border-radius: 50%;
        line-height: 32px;
        font-size: 16px;
        font-style: normal;
        text-align: center;
        background-color: #6ac6c4;
        color: #fff;
        margin-right: 8px;
        &.inactive {
          background-color: #e45049;
        }
      }
    }
    .flex {
      line-height: 20px;
      font-size: 14px;
      color: #999;
    }
  }
}
.modal-env-add {
  position: relative;
  min-height: 290px;
  padding: 10px 10px 10px 0;
  .env-gap {
    display: block;
    margin: 18px auto 0 auto;
    width: 14px;
    height: 1px;
    background-color: #ccc;
  }
}
  .modal-env-add /deep/ {
    .env-cpu {
      input {
        text-align: center;
      }
    }
  }
  .env-config-import {
    padding: 20px 0;
    &:hover {
      color: #2d8cf0;
    }
  }
</style>
